<template>
  <div class="chart-wrapper">
    <CustomLegend
      :colors="colors"
      :data="legend.data"
      :config="customLegend"
      v-if="customLegend"
      @change="handleCustomLegend"
    />
    <div ref="chart" :style="{ height: rawHeight }"></div>
  </div>
</template>
<script lang="ts">
import echarts, { EChartOption } from 'echarts'
import { mixins } from 'vue-class-component'
import ResizeMixin from './mixins/resize'
import { Component, Prop, Watch } from 'vue-property-decorator'
import CustomLegend from './CustomLegend.vue'

function mergeOpt(old: any, source: any) {
  if (!source) {
    return old
  }
  for (const [key, value] of Object.entries(source)) {
    const type = typeof value
    if (
      type === 'string' ||
      type === 'number' ||
      type === 'boolean' ||
      type === 'function'
    ) {
      old[key] = value
    } else if (Array.isArray(value)) {
      // empty old arr
      mergeOpt((old[key] = []), value)
    } else {
      mergeOpt((old[key] = old[key] || {}), source[key])
    }
  }
  return old
}

export const color = [
  '#1890FF',
  '#F7B500',
  '#50E3C2',
  '#6236FF',
  '#FA6400',
  '#9D6612',
  '#32C5FF',
  '#FF69A6',
  '#67C23A',
  '#FF5555',
  '#FFEC3D',
  '#B620E0'
]
function getDefaultOpt() {
  return {
    color,
    xAxis: {
      splitLine: {
        show: true,
        lineStyle: {
          type: 'dashed',
          color: '#EFF1F5'
        }
      },
      axisLine: {
        lineStyle: {
          color: '#E0E7FF'
        }
      },
      axisTick: {
        show: false
      },
      axisLabel: {
        color: '#9AA7BC'
      },
      minorSplitLine: {
        show: true,
        lineStyle: {
          color: '#ddd'
        }
      }
    },
    yAxis: {
      splitLine: {
        show: true,
        lineStyle: {
          type: 'dashed',
          color: '#EFF1F5'
        }
      },
      axisLine: {
        show: false
      },
      axisTick: {
        show: false
      },

      axisLabel: {
        color: '#9AA7BC'
      },
      minorSplitLine: {
        show: true,
        lineStyle: {
          color: '#ddd'
        }
      }
    }
  }
}

@Component({
  components: { CustomLegend }
})
export default class Chart extends mixins(ResizeMixin) {
  @Prop({ default: 500 }) height?: number | string
  @Prop() option?: EChartOption
  @Prop({ type: [Boolean, Object] }) customLegend?: boolean | object

  @Watch('option')
  onOptChange() {
    this.setOpt()
  }
  get legend() {
    if (this.option && this.option.legend) {
      return this.option.legend
    }
    return { data: [] }
  }
  get colors() {
    if (!this.option) {
      return color
    }
    return this.option.color || color
  }

  mounted() {
    this.init()
  }
  init() {
    this.$nextTick().then(() => {
      //@ts-ignore
      this.chart = echarts.init(this.$refs.chart)
      this.setOpt()
    })
  }

  beforeDestroy() {
    if (!this.chart) {
      return
    }
    this.chart.dispose()
    this.chart = null
  }

  handleCustomLegend(selected: any) {
    this.chart &&
      this.chart.setOption({
        legend: {
          selected
        }
      })
  }

  setOpt() {
    if (this.chart) {
      if (!this.option) {
        this.chart.clear()
      } else {
        const opt = mergeOpt(getDefaultOpt(), this.option)
        this.chart.setOption(opt)
      }
    }
  }
  get rawHeight() {
    return typeof this.height === 'string' ? this.height : this.height + 'px'
  }
}
</script>
<style scoped lang="scss">
.chart-wrapper {
  position: relative;
}
</style>
